module branch_predict_global (
    input wire clk, rst,
    
    input wire flushD,
    input wire stallD,

    input wire [31:0] pcF,
    input wire [31:0] pcM,

    input wire branchM,         // M阶段是否是分支指令
    input wire actual_takeM,    // 实际是否跳转

    input wire isWrong,
    input wire branchD,         // 译码阶段是否是跳转指令 
            
    output wire pred_takeD      // 预测是否跳转
);

    wire pred_takeF;
    reg pred_takeF_r;

// 定义参数
    parameter Strongly_not_taken = 2'b00, Weakly_not_taken = 2'b01, Weakly_taken = 2'b11, Strongly_taken = 2'b10;
    parameter PHT_DEPTH = 6;

// 
    reg [5:0] GHRD;
    reg [5:0] GHRM;
    reg [1:0] PHT [(1<<PHT_DEPTH)-1 : 0];
    
    integer i,j;
    wire [(PHT_DEPTH-1):0] PHT_index;

// ---------------------------------------预测逻辑---------------------------------------

    assign pred_takeF = PHT[GHRD][1];      // 在取指阶段预测是否会跳转，并经过流水线传递给译码阶段令

        // --------------------------pipeline------------------------------
            always @(posedge clk) begin
                if(rst | flushD) begin
                    pred_takeF_r <= 0;
                end
                else if(~stallD) begin
                    pred_takeF_r <= pred_takeF;
                end
            end
        // --------------------------pipeline------------------------------

// ---------------------------------------预测逻辑---------------------------------------


// ---------------------------------------GHRD初始化以及更新---------------------------------------

    always@(posedge clk) begin
        if(rst) begin
            GHRD<=0;
        end
        // 预测错误
        else if (isWrong) begin
            GHRD=GHRM;
        end
        else if(branchD) begin
            GHRD=GHRD<<1;
            GHRD[0]=pred_takeD;
        end
    end

// ---------------------------------------GHRD初始化以及更新---------------------------------------


// ---------------------------------------GHRM初始化以及更新---------------------------------------

    always@(posedge clk) begin
        if(rst) begin
            GHRM<=0;
        end
        else if(branchM) begin
            GHRM=GHRM<<1;
            GHRM[0]=actual_takeM;
        end
    end

// ---------------------------------------GHRM初始化以及更新---------------------------------------


// ---------------------------------------PHT初始化以及更新---------------------------------------
    always @(posedge clk) begin
        if(rst) begin
            for(i = 0; i < (1<<PHT_DEPTH); i=i+1) begin
                PHT[i] <= Weakly_taken;
            end
        end
        else begin
            case(PHT[GHRM])
                Strongly_not_taken: 
                    if (actual_takeM) begin
                        PHT[GHRM]<=Weakly_not_taken;
                    end
                Weakly_not_taken: 
                    if (actual_takeM) begin
                        PHT[GHRM]<=Weakly_taken;
                    end
                    else begin
                        PHT[GHRM]<=Strongly_not_taken;
                    end
                Weakly_taken: 
                    if (actual_takeM) begin
                        PHT[GHRM]<=Strongly_taken;
                    end
                    else begin
                        PHT[GHRM]<=Weakly_not_taken;
                    end
                Strongly_taken: 
                    if (!actual_takeM) begin
                        PHT[GHRM]<=Weakly_taken;
                    end
            endcase 
        end
    end
// ---------------------------------------PHT初始化以及更新---------------------------------------

    // 译码阶段输出最终的预测结果
    assign pred_takeD = branchD & pred_takeF_r;  
endmodule